package com.github.aloxc.plugin.restplus.resolver;

import com.github.aloxc.plugin.restplus.annotations.MicronautControllerAnnotataion;
import com.github.aloxc.plugin.restplus.annotations.MicronautRequestParamAnnotations;
import com.github.aloxc.plugin.restplus.common.Consts;
import com.github.aloxc.plugin.restplus.common.DesUtil;
import com.github.aloxc.plugin.restplus.common.PsiAnnotationSearchUtil;
import com.github.aloxc.plugin.restplus.entity.*;
import com.github.aloxc.plugin.restplus.method.RequestPath;
import com.github.aloxc.plugin.restplus.micronaut.MicronautAnnotationHelper;
import com.github.aloxc.plugin.restplus.navigation.action.RestServiceItem;
import com.github.aloxc.plugin.restplus.utils.Log;
import com.github.aloxc.plugin.restplus.utils.StringUtils;
import com.intellij.openapi.module.Module;
import com.intellij.openapi.progress.ProcessCanceledException;
import com.intellij.openapi.project.Project;
import com.intellij.psi.*;
import com.intellij.psi.impl.java.stubs.index.JavaAnnotationIndex;
import com.intellij.psi.search.GlobalSearchScope;

import java.util.ArrayList;
import java.util.Collection;
import java.util.List;

/**
 * Micronaut
 * @author liyh
 */
public class MicronautResolver extends BaseServiceResolver {
    public MicronautResolver(Module module) {
        myModule = module;
    }

    public MicronautResolver(Project project) {
        myProject = project;
    }
    @Override
    public List<RestServiceItem> getRestServiceItemList(Project project, GlobalSearchScope globalSearchScope) {
        List<RestServiceItem> itemList = new ArrayList<>();

//        for (PathMappingAnnotation supportedAnnotation : JaxrsPathAnnotation.values()) {

// 标注了 jaxrs Path 注解的类
//            Collection<PsiAnnotation> psiAnnotations = JavaAnnotationIndex.getInstance().get(supportedAnnotation.getShortName(), project, globalSearchScope);
        Collection<PsiAnnotation> psiAnnotations = JavaAnnotationIndex.getInstance().get(MicronautControllerAnnotataion.CONTROLLER.getShortName(), project, globalSearchScope);
        for (PsiAnnotation psiAnnotation : psiAnnotations) {
            PsiModifierList psiModifierList = (PsiModifierList) psiAnnotation.getParent();
            PsiElement psiElement = psiModifierList.getParent();

            if (!(psiElement instanceof PsiClass)) {
                continue;
            }

            PsiClass psiClass = (PsiClass) psiElement;
            PsiMethod[] psiMethods = psiClass.getMethods();
            if(null == psiClass.getModifierList().findAnnotation(MicronautControllerAnnotataion.CONTROLLER.getQualifiedName())){
                continue;
            }
            if (psiMethods == null) {
                continue;
            }

//                psiMethodList.addAll(Arrays.asList(psiMethods));

            String classUriPath = MicronautAnnotationHelper.getClassUriPath(psiClass);

            for (PsiMethod psiMethod : psiMethods) {

                RequestPath[] methodUriPaths = MicronautAnnotationHelper.getRequestPaths(psiMethod);
                for (RequestPath methodUriPath : methodUriPaths) {
                    RestServiceItem item = createRestServiceItem(psiClass,psiMethod, classUriPath, methodUriPath,false);
                    itemList.add(item);
                }
            }

        }
//        }
        return itemList;
    }

    @Override
    public List<RestServiceItem> getServiceItemList(PsiClass psiClass) {

        PsiMethod[] psiMethods = psiClass.getMethods();
        if (psiMethods == null) {
            return new ArrayList<>();
        }
        List<RestServiceItem> itemList = new ArrayList<>();
        try {
            List<RequestPath> classRequestPaths = MicronautAnnotationHelper.getRequestPaths(psiClass);
            for (PsiMethod psiMethod : psiMethods) {
                RequestPath[] methodRequestPaths = MicronautAnnotationHelper.getRequestPaths(psiMethod);
                PsiParameterList parameterList = psiMethod.getParameterList();
                PsiParameter[] parameters = parameterList.getParameters();
                boolean foundRequestBody = false;
                for (PsiParameter psiParameter : parameters) {
                    PsiModifierList modifierList = psiParameter.getModifierList();
                    foundRequestBody = modifierList.findAnnotation(MicronautRequestParamAnnotations.REQUEST_BODY.getQualifiedName()) != null;

                }
                for (RequestPath classRequestPath : classRequestPaths) {
                    for (RequestPath methodRequestPath : methodRequestPaths) {
                        String path = classRequestPath.getPath();
                        RestServiceItem item = createRestServiceItem(psiClass,psiMethod, path, methodRequestPath, foundRequestBody);
                        itemList.add(item);
                    }
                }
            }
        } catch (ProcessCanceledException e) {
            Log.log("MicronautResolver", e.getMessage());
        }
        return itemList;
    }

    @Override
    public void getYapiRequest(Project project, YapiDTO YapiDTO, PsiMethod psiMethod) {
        PsiParameter[] psiParameters = psiMethod.getParameterList().getParameters();
        if (psiParameters.length > 0) {
            ArrayList list = new ArrayList<YapiQueryDTO>();
            List<YapiHeaderDTO> yapiHeaderDTOList = new ArrayList<>();
            List<YapiPathVariableDTO> yapiPathVariableDTOList = new ArrayList<>();
            for (PsiParameter psiParameter : psiParameters) {
                if (Consts.JAVA.HTTP_SERVLET_REQUEST.equals(psiParameter.getType().getCanonicalText()) || Consts.JAVA.HTTP_SERVLET_RESPONSE.equals(psiParameter.getType().getCanonicalText())) {
                    continue;
                }
                PsiAnnotation psiAnnotation = PsiAnnotationSearchUtil.findAnnotation(psiParameter, MicronautRequestParamAnnotations.REQUEST_BODY.getQualifiedName());
                if (psiAnnotation != null) {
                    YapiDTO.setRequestBody(getYapiResponse(project, psiParameter.getType()));
                } else {
                    psiAnnotation = PsiAnnotationSearchUtil.findAnnotation(psiParameter, MicronautRequestParamAnnotations.REQUEST_PARAM.getQualifiedName());
                    YapiHeaderDTO yapiHeaderDTO = null;
                    YapiPathVariableDTO yapiPathVariableDTO = null;
                    if (psiAnnotation == null) {
                        psiAnnotation = PsiAnnotationSearchUtil.findAnnotation(psiParameter, MicronautRequestParamAnnotations.REQUEST_ATTRIBUTE.getQualifiedName());
                        if (psiAnnotation == null) {
                            psiAnnotation = PsiAnnotationSearchUtil.findAnnotation(psiParameter, MicronautRequestParamAnnotations.REQUEST_HEADER.getQualifiedName());
                            if (psiAnnotation == null) {
                                psiAnnotation = PsiAnnotationSearchUtil.findAnnotation(psiParameter, MicronautRequestParamAnnotations.PATH_VARIABLE.getQualifiedName());
                                yapiPathVariableDTO = new YapiPathVariableDTO();
                            } else {
                                yapiHeaderDTO = new YapiHeaderDTO();
                            }
                        }
                    }
                    if (psiAnnotation != null) {
                        PsiNameValuePair[] psiNameValuePairs = psiAnnotation.getParameterList().getAttributes();
                        YapiQueryDTO yapiQueryDTO = new YapiQueryDTO();

                        if (psiNameValuePairs.length > 0) {
                            for (PsiNameValuePair psiNameValuePair : psiNameValuePairs) {
                                if ("name".equals(psiNameValuePair.getName()) || "value".equals(psiNameValuePair.getName())) {
                                    if (yapiHeaderDTO != null) {
                                        yapiHeaderDTO.setName(psiNameValuePair.getValue().getText().replace("\"", ""));
                                    } else if (yapiPathVariableDTO != null) {
                                        yapiPathVariableDTO.setName(psiNameValuePair.getValue().getText().replace("\"", ""));
                                    } else {
                                        yapiQueryDTO.setName(psiNameValuePair.getValue().getText().replace("\"", ""));
                                    }
                                } else if ("required".equals(psiNameValuePair.getName())) {
                                    yapiQueryDTO.setName(psiParameter.getName());
                                    yapiQueryDTO.setRequired(psiNameValuePair.getValue().getText().replace("\"", "").replace("false", "0").replace("true", "1"));
                                } else if ("defaultValue".equals(psiNameValuePair.getName())) {
                                    if (yapiHeaderDTO != null) {
                                        yapiHeaderDTO.setExample(psiNameValuePair.getValue().getText().replace("\"", ""));
                                    } else {
                                        yapiQueryDTO.setExample(psiNameValuePair.getValue().getText().replace("\"", ""));
                                    }
                                } else {
                                    if (yapiHeaderDTO != null) {
                                        yapiHeaderDTO.setName(StringUtils.isNotBlank(psiNameValuePair.getLiteralValue()) ? psiNameValuePair.getLiteralValue() : psiParameter.getName());
                                        // 通过方法注释获得 描述 加上 类型
                                        yapiHeaderDTO.setDesc(DesUtil.getParamDesc(psiMethod, psiParameter.getName()) + "(" + psiParameter.getType().getPresentableText() + ")");
                                    }
                                    if (yapiPathVariableDTO != null) {
                                        yapiPathVariableDTO.setName(StringUtils.isNotBlank(psiNameValuePair.getLiteralValue()) ? psiNameValuePair.getLiteralValue() : psiParameter.getName());
                                        // 通过方法注释获得 描述 加上 类型
                                        yapiPathVariableDTO.setDesc(DesUtil.getParamDesc(psiMethod, psiParameter.getName()) + "(" + psiParameter.getType().getPresentableText() + ")");
                                    } else {
                                        yapiQueryDTO.setName(StringUtils.isNotBlank(psiNameValuePair.getLiteralValue()) ? psiNameValuePair.getLiteralValue() : psiParameter.getName());
                                        // 通过方法注释获得 描述 加上 类型
                                        yapiQueryDTO.setDesc(DesUtil.getParamDesc(psiMethod, psiParameter.getName()) + "(" + psiParameter.getType().getPresentableText() + ")");
                                    }
                                    if (NormalTypes.normalTypes.containsKey(psiParameter.getType().getPresentableText())) {
                                        if (yapiHeaderDTO != null) {
                                            yapiHeaderDTO.setExample(NormalTypes.normalTypes.get(psiParameter.getType().getPresentableText()).toString());
                                        } else if (yapiPathVariableDTO != null) {
                                            yapiPathVariableDTO.setExample(NormalTypes.normalTypes.get(psiParameter.getType().getPresentableText()).toString());
                                        } else {
                                            yapiQueryDTO.setExample(NormalTypes.normalTypes.get(psiParameter.getType().getPresentableText()).toString());
                                        }
                                    } else {
                                        YapiDTO.setRequestBody(getYapiResponse(project, psiParameter.getType()));
                                    }
                                }
                            }
                        } else {
                            if (yapiHeaderDTO != null) {
                                yapiHeaderDTO.setName(psiParameter.getName());
                                // 通过方法注释获得 描述 加上 类型
                                yapiHeaderDTO.setDesc(DesUtil.getParamDesc(psiMethod, psiParameter.getName()) + "(" + psiParameter.getType().getPresentableText() + ")");
                            } else if (yapiPathVariableDTO != null) {
                                yapiPathVariableDTO.setName(psiParameter.getName());
                                // 通过方法注释获得 描述 加上 类型
                                yapiPathVariableDTO.setDesc(DesUtil.getParamDesc(psiMethod, psiParameter.getName()) + "(" + psiParameter.getType().getPresentableText() + ")");
                            } else {
                                yapiQueryDTO.setName(psiParameter.getName());
                                // 通过方法注释获得 描述 加上 类型
                                yapiQueryDTO.setDesc(DesUtil.getParamDesc(psiMethod, psiParameter.getName()) + "(" + psiParameter.getType().getPresentableText() + ")");
                            }
                            if (NormalTypes.normalTypes.containsKey(psiParameter.getType().getPresentableText())) {
                                if (yapiHeaderDTO != null) {
                                    yapiHeaderDTO.setExample(NormalTypes.normalTypes.get(psiParameter.getType().getPresentableText()).toString());
                                } else if (yapiPathVariableDTO != null) {
                                    yapiPathVariableDTO.setExample(NormalTypes.normalTypes.get(psiParameter.getType().getPresentableText()).toString());
                                } else {
                                    yapiQueryDTO.setExample(NormalTypes.normalTypes.get(psiParameter.getType().getPresentableText()).toString());
                                }
                            } else {
                                YapiDTO.setRequestBody(getYapiResponse(project, psiParameter.getType()));
                            }
                        }
                        if (yapiHeaderDTO != null) {
                            if (StringUtils.isNullOrEmpty(yapiHeaderDTO.getDesc())) {
                                // 通过方法注释获得 描述  加上 类型
                                yapiHeaderDTO.setDesc(DesUtil.getParamDesc(psiMethod, psiParameter.getName()) + "(" + psiParameter.getType().getPresentableText() + ")");
                            }
                            if (StringUtils.isNullOrEmpty(yapiHeaderDTO.getExample()) && NormalTypes.normalTypes.containsKey(psiParameter.getType().getPresentableText())) {
                                yapiHeaderDTO.setExample(NormalTypes.normalTypes.get(psiParameter.getType().getPresentableText()).toString());
                            }
                            yapiHeaderDTOList.add(yapiHeaderDTO);
                        } else if (yapiPathVariableDTO != null) {
                            if (StringUtils.isNullOrEmpty(yapiPathVariableDTO.getDesc())) {
                                // 通过方法注释获得 描述  加上 类型
                                yapiPathVariableDTO.setDesc(DesUtil.getParamDesc(psiMethod, psiParameter.getName()) + "(" + psiParameter.getType().getPresentableText() + ")");
                            }
                            if (StringUtils.isNullOrEmpty(yapiPathVariableDTO.getExample()) && NormalTypes.normalTypes.containsKey(psiParameter.getType().getPresentableText())) {
                                yapiPathVariableDTO.setExample(NormalTypes.normalTypes.get(psiParameter.getType().getPresentableText()).toString());
                            }
                            yapiPathVariableDTOList.add(yapiPathVariableDTO);
                        } else {
                            if (StringUtils.isNullOrEmpty(yapiQueryDTO.getDesc())) {
                                // 通过方法注释获得 描述 加上 类型
                                yapiQueryDTO.setDesc(DesUtil.getParamDesc(psiMethod, psiParameter.getName()) + "(" + psiParameter.getType().getPresentableText() + ")");
                            }
                            if (StringUtils.isNullOrEmpty(yapiQueryDTO.getExample()) && NormalTypes.normalTypes.containsKey(psiParameter.getType().getPresentableText())) {
                                yapiQueryDTO.setExample(NormalTypes.normalTypes.get(psiParameter.getType().getPresentableText()).toString());
                            }
                            list.add(yapiQueryDTO);
                        }
                    } else {
                        // 支持实体对象接收
                        YapiDTO.setReq_body_type("form");
                        if (YapiDTO.getReq_body_form() != null) {
                            YapiDTO.getReq_body_form().addAll(getYapiRequestForm(project, psiParameter, psiMethod));
                        } else {
                            YapiDTO.setReq_body_form(getYapiRequestForm(project, psiParameter, psiMethod));
                        }
                    }
                }
            }
            YapiDTO.setParams(list);
            YapiDTO.setHeader(yapiHeaderDTOList);
            YapiDTO.setReq_params(yapiPathVariableDTOList);
        }
    }

}
